﻿/**
 * 
 * T是泛型参数。where T : class  是对T的限制，这里的意思是T必须是引用类型，包括任何类、接口、委托或数组类型。
 * http://msdn.microsoft.com/zh-cn/library/d5x73970%28v=vs.80%29.aspx 
 * 
 * **/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Reflection;
using log4net;

namespace LIMS.DALFactory
{
    /// <summary>
    /// 泛型工厂创建制定的实例对象
    /// </summary>
    /// <typeparam name="T">接口的约束类型</typeparam>
    public class DataAccess<T> where T : class
    {
        #region 读取配置文件
        /// <summary>
        /// 指定类型的后缀字段
        /// </summary>
        private static readonly String Service = "Service";

        /// <summary>
        /// 指定程序集（SqlServerDAL）在配置文件的Key值
        /// </summary>
        private static readonly String WebDalKey = "WebDAL";

        /// <summary>
        ///读取配置文件的SqlServerDAL程序集名称
        /// </summary>
        private static readonly String dllPath = ConfigurationManager.AppSettings[WebDalKey].ToString();
        #endregion

        #region 创建实现该接口的实例对象
        /// <summary>
        /// 根据指定类型<remarks>T</remarks>，获取该类型的对应配置文件指定的Key值
        /// </summary>
        /// <typeparam name="TEntity">约束：指定的接口类型</typeparam>
        /// <returns>返回该类型在DAL层实现该接口的实例对象</returns>
        private static String GetConfigKey<TEntity>()
        {
            //获取指定类型的全命名空间  
            //eg:  LIMS.IDAL.IAdmin  ----> IAdmin  ----> Admin ----> AdminService ----> AppSettings["AdminService"] 
            String configKey = typeof(TEntity).Name.Substring(1) + Service;
            return ConfigurationManager.AppSettings[configKey].ToString();
        }

        /// <summary>
        /// 创建缓存对象
        /// </summary>
        private static DefaultCacheAdapter cacheFactory = new DefaultCacheAdapter();

        /// <summary>
        /// 创建指定类型<remarks>T</remarks>的实例
        /// </summary>
        /// <returns>返回创建的实例对象</returns>
        public static T CreateObject()
        {
            String classNameSpace = GetConfigKey<T>();
            Object objData = cacheFactory.Get<T>(classNameSpace);
            if (objData == null)
            {
                //运用反射创建对象实例
                objData = Assembly.Load(dllPath).CreateInstance(classNameSpace);

                //Key:实例对象的命名空间    value:对象实例
                cacheFactory.Add(classNameSpace, objData);
            }
            return (T)objData;
        }

        #endregion

    }
}